<?php

class CW_XslClass {

	private $variables;
	private $templates;

	public $xsl_doctype_public;
	public $xsl_doctype_system;
	public $xsl_method;
	public $xsl_omit_xml_declaration;
	public $xsl_encoding;
	public $xsl_indent;

	public function __construct()
	{
		$this->variables = array();
		$this->templates = array();
		$this->xml_buffer = '';

		$this->xsl_doctype_public = '-//W3C//DTD XHTML 1.0 Strict//EN';
		$this->xsl_doctype_system = 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd';
		$this->xsl_method = 'xml';
		$this->xsl_omit_xml_declaration = 'yes';
		$this->xsl_encoding = 'UTF-8';
		$this->xsl_indent = 'yes';
	}

	public function useXsl()
	{
		return $this->templates;
	}

	public function addTemplate($file)
	{
		$file = str_replace(DIRECTORY_SEPARATOR, '/', $file);

		if(false == file_exists($file))
		{
			throw new CoreException("Xsl template '{$file}' could not be located!");
		}

		if(false == in_array($file, $this->templates))
		{
			$this->templates[] = $file;
		}

		return true;
	}

	public function addVariable($name, $value)
	{
		$this->variables[$name] = $value;

		return true;
	}

	public function buildXslOutput()
	{
		$output  = "<?xml version=\"1.0\" encoding=\"{$this->xsl_encoding}\"?>\n";
		$output .= "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n\n";

		foreach($this->templates as $template)
		{
			$output .= "\t<xsl:import href=\"{$template}\"/>\n";
		}

		$output .= "\n\t<xsl:output method=\"{$this->xsl_method}\"\n";
		$output .= "\t\tdoctype-public=\"{$this->xsl_doctype_public}\"\n";
		$output .= "\t\tdoctype-system=\"{$this->xsl_doctype_system}\"\n";
		$output .= "\t\tomit-xml-declaration=\"{$this->xsl_omit_xml_declaration}\"\n";
		$output .= "\t\tencoding=\"{$this->xsl_encoding}\"\n";
		$output .= "\t\tindent=\"{$this->xsl_indent}\"/>\n";
		$output .= "\n\t<xsl:template match=\"/\">\n";
		$output .= "\t\t<xsl:apply-templates/>\n";
		$output .= "\t</xsl:template>\n\n";
		$output .= "</xsl:stylesheet>";

		return $output;
	}

	private function translateDOMXML($xml)
	{
		$xsl_data = domxml_xslt_stylesheet($this->buildXslOutput());

		return $xsl_data->result_dump_mem($xsl_data->process(domxml_open_mem($xml), $this->variables));
	}

	private function translateSablotron($xml)
	{
		return xslt_process(xslt_create(), 'arg:/xml', 'arg:/xsl', NULL, array('/xml' => $xml, '/xsl' => $this->buildXslOutput()), $this->variables);
	}

	private function translateXsltProcessor($xml)
	{
		$Xslt = new XsltProcessor;

		foreach($this->variables as $name => $value)
		{
			$Xslt->setParameter('', $name, $value);
		}

		$Xslt->importStyleSheet(DomDocument::loadXML($this->buildXslOutput()));

		return $Xslt->transformToXML(DomDocument::loadXML($xml));
	}

	public function transform($xml)
	{
		if(function_exists('domxml_xslt_stylesheet_file'))
		{
			return $this->translateDOMXML($xml);
		}
		else if(function_exists('xslt_create'))
		{
			return $this->translateSablotron($xml);
		}
		else if(class_exists('XsltProcessor'))
		{
			return $this->translateXsltProcessor($xml);
		}
		else
		{
			throw new CoreException('XSLT support not found! Please consult your host and ask to enable this feature.');
		}

		return false;
	}
}

?>